
%{
#include "lexer.hpp"
#include <iostream>
#include <istream>
#include <ostream>
using std::istream;

#include "Value.hpp"
typedef ptr<Object> ObjectPtr;

#include "ParsingErrorException.hpp"

#define YY_USER_ACTION prepareForAction();

int yyFlexLexer::yywrap() { return 1; }

%}

%option yyclass="Lexer"

%%

if {
	return yy::parser::token::KEYWORD_IF;
}
elif {
	return yy::parser::token::KEYWORD_ELIF;
}
else {
	return yy::parser::token::KEYWORD_ELSE;
}
end {
	return yy::parser::token::KEYWORD_END;
}
for {
	return yy::parser::token::KEYWORD_FOR;
}
next {
	return yy::parser::token::KEYWORD_NEXT;
}
while {
	return yy::parser::token::KEYWORD_WHILE;
}
repeat {
	return yy::parser::token::KEYWORD_REPEAT;
}
true {
	yylval = new BoolValue(true);
	return yy::parser::token::LITERAL;
}
false {
	yylval = new BoolValue(false);
	return yy::parser::token::LITERAL;
}
[[:alpha:]][[:alpha:][:digit:]_]* {
	yylval = new StrValue(yytext);
	return yy::parser::token::NAME;
}
[;,()=] {
	return (int)yytext[0];
}
\@T {
	std::pair<String, SourceLocation> block = preprocessor_.takeTextBlock();
	yylval = new StrValue(block.first);
	yylloc = block.second;
	position_ = yylloc.end();
	
	char c = block.first.empty() ? '\0' : block.first.at(block.first.size()-1);
	if(c == '\n')
		position_.newLine();
	else
		position_.newChar();
	return yy::parser::token::LITERAL;
}
\@P {
	position_ = preprocessor_.takePosition();
	/* continue scanning */
}
\:\= |
\+\= |
\-\= |
\*\= |
\/\= |
\%\= |
\|\= |
\&\= |
\^\= |
\<\<\= |
\>\>\= |
\$\= {
	yylval = new StrValue(yytext);
	return yy::parser::token::OP_ASSIGN;
}
\< |
\> |
\<\= |
\>\= |
\=\= |
\!\= {
	yylval = new StrValue(yytext);
	return yy::parser::token::OP_BINARY_0;
}
\| |
\^ |
\$ {
	yylval = new StrValue(yytext);
	return yy::parser::token::OP_BINARY_1;
}
\* |
\/ |
\% |
\& |
\<\< |
\>\> {
	yylval = new StrValue(yytext);
	return yy::parser::token::OP_BINARY_2;
}
\~|\! {
	yylval = new StrValue(yytext);
	return yy::parser::token::OP_UNARY;
}
\+|\- {
	yylval = new StrValue(yytext);
	return yy::parser::token::OP_XNARY;
}
0[xX][[:digit:][:alpha:]]+ {
	yylval = new IntValue(parseInt(yytext + 2, 16));
	return yy::parser::token::LITERAL;
}
0[bB][[:digit:]]+ {
	yylval = new IntValue(parseInt(yytext + 2, 2));
	return yy::parser::token::LITERAL;
}
0[cC][[:digit:]]+ {
	yylval = new IntValue(parseInt(yytext + 2, 8));
	return yy::parser::token::LITERAL;
}
0[dD][[:digit:]]+ {
	yylval = new IntValue(parseInt(yytext + 2, 10));
	return yy::parser::token::LITERAL;
}
[[:digit:]]+ {
	yylval = new IntValue(parseInt(yytext, 10));
	return yy::parser::token::LITERAL;
}
[[:digit:]]+\.[[:digit:]]*([eE][+-]?[[:digit:]]+)? |
[[:digit:]]+[eE][+-]?[[:digit:]]+ |
\.[[:digit:]]+[[:digit:]]*([eE][+-]?[[:digit:]]+)? {
	yylval = new RealValue(parseReal(yytext));
	return yy::parser::token::LITERAL;
}
\"([^"\\\n]|\\.)*\" |
\'([^'\\\n]|\\.)*\' {
	yytext[yyleng-1] = '\0';
	yylval = new StrValue(unescape(yytext+1)); return yy::parser::token::LITERAL;
}
\"([^"\\\n]|\\.)*\n |
\'([^'\\\n]|\\.)*\n {
	throw ParsingErrorException(SourceLocation(), "Unterminated string literal");
}
\n {
	position_.newLine();
}
[[:space:]]+ {
	/* eat spaces */
}
. {
	std::cerr << "Unexpected character: \'" << yytext << "\'" << std::endl;
}
%%